import os
import random
import pickle
import numpy as np
import torch
import scipy.io


def _fetch(path, name):
    if name == 'train':
        token_file = path + '/bow_tr_tokens.mat'
        count_file = path + '/bow_tr_counts.mat'
        doc_id_file = path + '/bow_tr_ids.mat'
    elif name == 'valid':
        token_file = path + '/bow_va_tokens.mat'
        count_file = path + '/bow_va_counts.mat'
        doc_id_file = path + '/bow_va_ids.mat'
    else:
        token_file = path + '/bow_ts_tokens.mat'
        count_file = path + '/bow_ts_counts.mat'
        doc_id_file = None
    tokens = scipy.io.loadmat(token_file)['tokens'].squeeze()
    counts = scipy.io.loadmat(count_file)['counts'].squeeze()
    if doc_id_file is not None:
        ids = scipy.io.loadmat(doc_id_file)['ids'].squeeze()
    else:
        ids = None

    if name == 'test':
        token_1_file = path + '/bow_ts_h1_tokens.mat'
        count_1_file = path + '/bow_ts_h1_counts.mat'
        token_2_file = path + '/bow_ts_h2_tokens.mat'
        count_2_file = path + '/bow_ts_h2_counts.mat'
        tokens_1 = scipy.io.loadmat(token_1_file)['tokens'].squeeze()
        counts_1 = scipy.io.loadmat(count_1_file)['counts'].squeeze()
        tokens_2 = scipy.io.loadmat(token_2_file)['tokens'].squeeze()
        counts_2 = scipy.io.loadmat(count_2_file)['counts'].squeeze()
        return {'tokens': tokens, 'counts': counts,
                'tokens_1': tokens_1, 'counts_1': counts_1,
                'tokens_2': tokens_2, 'counts_2': counts_2}
    return {'tokens': tokens, 'counts': counts, 'ids': ids}


def get_data(path):
    with open(path + '/vocab.pkl', 'rb') as f:
        vocab = pickle.load(f)

    train = _fetch(path, 'train')
    valid = _fetch(path, 'valid')
    test = _fetch(path, 'test')

    return vocab, train, valid, test


def get_batch(tokens, counts, ind, vocab_size, device, emsize=300):
    """fetch input data by batch."""
    batch_size = len(ind)
    data_batch = np.zeros((batch_size, vocab_size))

    for i, doc_id in enumerate(ind):
        doc = tokens[doc_id]
        count = counts[doc_id]
        if len(doc) == 1:
            doc = [doc.squeeze()]
            count = [count.squeeze()]
        else:
            doc = doc.squeeze()
            count = count.squeeze()
        if doc_id != -1:
            for j, word in enumerate(doc):
                data_batch[i, word] = count[j]
    data_batch = torch.from_numpy(data_batch).float().to(device)
    return data_batch
